/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package model;

import HibernateConfig.HibernateUtil;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import static java.lang.Math.round;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

/**
 *
 * @author Enrique
 */

// CLASE QUE SE ENCARGA DE LA OBTENCION DE LOS RATIOS DE CRECIMIENTO DE LAS CIUDADES

public class Ratios {
    
    
    // ATRIBUTOS
    
    
    // CONSTRUCTORES
    
    
    // SETTERS Y GETTERS
    
    
    // METODOS
    
    
    // metodo que lee archivos de data historica y obtiene los ratios de crecimiento
    public static void obtenerRatios(Simulacion Simu) throws FileNotFoundException, IOException{
        
        Map<String,String> mapaoaci= obtenermapaoaci(Simu);
        float minutos_sim=Simu.getMinutos_sim();
        List<Nodo> listaNodos=Simu.getListaNodos();
        String directorio=Simu.getDirectorio_archivos();
        int numarch=listaNodos.size();
        Map<String,Map<String,Integer>> mapa = new LinkedHashMap<String,Map<String,Integer>>();
        Map<String,Integer> mapaid= new LinkedHashMap<String,Integer>();

        for(int i=0;i<numarch;i++){
            String ciudad=listaNodos.get(i).getCiudad().getAbreviacion();
            String oasi=listaNodos.get(i).getCiudad().getOaci();
            Integer idd=listaNodos.get(i).getCiudad().getIdCiudad();
            mapaid.put(ciudad, idd);
            String ruta=directorio+File.separator+"arch_"+oasi+".txt";
            File archivo = new File (ruta);
            if(archivo.exists()){
                FileReader fr = new FileReader(archivo);
                int valor=1;         
                LinkedList<String> lista = new LinkedList<String>();
                Map<String,Integer> mapaux = new LinkedHashMap<String,Integer>();
                while(valor!=-1){     
                    valor=fr.read();
                    if(valor==-1)break;
                    String id="";
                    id=id+valor;
                    for(int j=0;j<8;j++){
                       valor=fr.read();
                       id=id+(char)valor;
                    }
                    String ano="";
                    for(int j=0;j<4;j++){
                       valor=fr.read();
                       ano=ano+(char)valor;
                    }
                    String mes="";
                    for(int j=0;j<2;j++){
                       valor=fr.read();
                       mes=mes+(char)valor;
                    }
                    String dia="";
                    for(int j=0;j<2;j++){
                       valor=fr.read();
                       dia=dia+(char)valor;
                    }
                    String hora="";
                    for(int j=0;j<5;j++){
                       valor=fr.read();
                       hora=hora+(char)valor;
                    }
                    String ciudestino="";
                    for(int j=0;j<4;j++){
                       valor=fr.read();
                       ciudestino=ciudestino+(char)valor;
                    }
                    ciudestino=mapaoaci.get(ciudestino);
                    String linea="";
                    linea=ciudestino+" "+ano+" "+mes+" "+dia+" "+hora;
                    lista.add(linea);
                    valor=fr.read();
                    valor=fr.read();
                }
                Collections.sort(lista);
                Iterator iter = lista.iterator();
                String cadena;
                int npaq=0;
                String destino="";
                int day=0;
                int month=0;
                int year=0;
                int ratio=0;
                int rat1=0;
                int grupo=0;
                while (iter.hasNext())
                {
                cadena = (String) iter.next();           
                StringTokenizer st = new StringTokenizer (cadena);
                String s2="";
                int numTokens=0;
                String des1="";
                int d1=0;
                int m1=0;
                int y1=0;
            // bucle por todas las palabras
                    while (st.hasMoreTokens())
                    {                  
                        s2 = st.nextToken();
                        numTokens++;
                        if(npaq==0){
                            if(numTokens==1){
                               destino=s2; 
                            }
                            if(numTokens==2){
                               year=Integer.parseInt(s2); 
                            }
                            if(numTokens==3){
                               month=Integer.parseInt(s2); 
                            }
                            if(numTokens==4){
                               day=Integer.parseInt(s2); 
                               day=day+7;
                               if(day>30){
                                   day=day-30;
                                   month++;
                                   if(month>12){
                                       month=month-12;
                                       year++;
                                   }                               
                               }
                            }
                        }
                        else{
                           if(numTokens==1){
                               des1=s2.toString(); 
                            }
                            if(numTokens==2){
                               y1=Integer.parseInt(s2.toString()); 
                            }
                            if(numTokens==3){
                               m1=Integer.parseInt(s2.toString()); 
                            }
                            if(numTokens==4){
                               d1=Integer.parseInt(s2.toString()); 
                               if(!des1.equals(destino)){
                                  grupo++;
                                  if(grupo==1){
                                      ratio=0;                                  
                                      mapaux.put(destino,ratio);
                                  }
                                  else if(grupo>1){
                                      ratio=ratio+(npaq-rat1);
                                      ratio=round(ratio/(grupo-1));
                                      float ratioaux=((float)(ratio)/7);
                                      ratioaux=(float)(ratioaux/24);
                                      ratioaux=(float)(ratioaux/60);
                                      float partedecimal=ratioaux-((int)ratioaux);
                                      if(partedecimal>0){
                                          ratio=round(ratioaux)+1;
                                      }
                                      else{
                                          ratio=round(ratioaux);
                                      }
                                      ratio=round(ratio*minutos_sim);
                                      mapaux.put(destino,ratio);
                                  }
                                  rat1=0;
                                  ratio=0;
                                  grupo=0;
                                  destino=des1;
                                  month=m1;
                                  year=y1;
                                  day=d1+7;
                                  if(day>30){
                                   day=day-30;
                                   month++;
                                   if(month>12){
                                       month=month-12;
                                       year++;
                                   }                               
                                  }
                                  npaq=0;
                              }
                              else if(y1>year){
                                  grupo++;
                                  if(grupo==1){
                                      rat1=npaq;
                                  }
                                  if(grupo>1){
                                      ratio=ratio+(npaq-rat1);
                                      rat1=npaq;
                                  }
                                   month=m1;
                                   year=y1;
                                   day=d1+7;
                                   if(day>30){
                                     day=day-30;
                                     month++;
                                    if(month>12){
                                       month=month-12;
                                       year++;
                                    }                                
                                  }
                               }
                               else if((m1>month)&&(y1==year)){
                                   grupo++;
                                  if(grupo==1){
                                      rat1=npaq;
                                  }
                                  if(grupo>1){
                                      ratio=ratio+(npaq-rat1);
                                      rat1=npaq;
                                  }
                                   month=m1;
                                   year=y1;
                                   day=d1+7;
                                   if(day>30){
                                     day=day-30;
                                     month++;
                                    if(month>12){
                                       month=month-12;
                                       year++;
                                    }                                
                                  }
                               }
                               else if ((d1>day)&&(m1>month)&&(y1==year)){
                                  grupo++;
                                  if(grupo==1){
                                      rat1=npaq;
                                  }
                                  if(grupo>1){
                                      ratio=ratio+(npaq-rat1);
                                      rat1=npaq;
                                  }
                                   month=m1;
                                   year=y1;
                                   day=d1+7;
                                   if(day>30){
                                     day=day-30;
                                     month++;
                                    if(month>12){
                                       month=month-12;
                                       year++;
                                    }                                
                                  }
                               }
                            } 
                        }
                    }
                    npaq++;
                    System.out.println("Num. paquete = " + npaq);
                }
                grupo++;
                if(grupo==1){
                    ratio=0;
                    mapaux.put(destino,ratio);
                }
                else if(grupo>1){
                    ratio=ratio+(npaq-rat1);
                    ratio=round(ratio/(grupo-1));
                    float ratioaux=(((ratio/7)/24)/60);
                    float partedecimal=ratioaux-((int)ratioaux);
                    if(partedecimal>0){
                        ratio=round(ratioaux)+1;
                    }
                    else{
                        ratio=round(ratioaux);
                    }
                    ratio=round(ratio/**minutos_sim*/); 
                    mapaux.put(destino,ratio);
                }    
                mapa.put(ciudad, mapaux);
                fr.close();
            }
        }
        Simu.setArbolRatios(mapa);
        
        Iterator it = mapa.keySet().iterator();
        while(it.hasNext()){
          Object key = it.next();
          System.out.println("Clave: " + key + " -> Valor: " + mapa.get(key));
          Map<String,Integer> hijo=mapa.get(key);
          Iterator it2 = hijo.keySet().iterator();
            while(it2.hasNext()){
                Object key2 = it2.next();
                Integer rat=hijo.get(key2);
                rat=round(rat/minutos_sim);
                Integer origen=mapaid.get(key);
                Integer destino=mapaid.get(key2);
                Integer esta=buscarRatiosBD(origen,destino);
                if(esta==-1) agregarRatiosBD(origen,destino,rat);
                else actualizarRatiosBD(origen,destino,rat);                               
            }
        }
    }
    
    public static Map obtenermapaoaci(Simulacion Simu) {
        Map<String,String> mapaoaci= new LinkedHashMap<String,String>();
        List<Nodo> listaNodos=Simu.getListaNodos();
        int numarch=listaNodos.size();
        
        for(int i=0;i<numarch;i++){
            String ciudad=listaNodos.get(i).getCiudad().getAbreviacion();
            String oasi=listaNodos.get(i).getCiudad().getOaci();
            mapaoaci.put(oasi, ciudad);
        }
        
        return mapaoaci;
    }
    
    // metodo para obtener los ratios desde la BD, solamente de los que esten guardados en ella
    public static void obtenerRatiosDesdeBD(Simulacion Simu){
        
        List<Nodo> listaNodos=Simu.getListaNodos();
        
        float minutos_sim=Simu.getMinutos_sim();
        int numarch=listaNodos.size();
        Map<String,Map<String,Integer>> mapa = new LinkedHashMap<String,Map<String,Integer>>();
        Map<Integer,String> mapaid= new LinkedHashMap<Integer,String>();
        for(int i=0;i<numarch;i++){
            String ciudad=listaNodos.get(i).getCiudad().getAbreviacion();
            Integer idd=listaNodos.get(i).getCiudad().getIdCiudad();
            mapaid.put(idd, ciudad);
        }
        LinkedList<String> lista = new LinkedList<String>();
        
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        Transaction transaccion = null;
        Map<String,Integer> mapaaux= new LinkedHashMap<String,Integer>();
        int i=0;
        String oriaux="";
        try
                {
                    transaccion = sesion.beginTransaction();
                    List ratios = sesion.createQuery("from RatioVuelo order by id_ciudad_origen").list();   // query para obtener todas las ciudades
                    Iterator iterador = ratios.iterator(); 
                    while (iterador.hasNext()){
                        RatioVuelo ratiotemp= (RatioVuelo)iterador.next();   
                        Integer ori=ratiotemp.getId().getIdCiudadOrigen();
                        Integer des=ratiotemp.getId().getIdCiudadDestino();
                        Integer rat=ratiotemp.getRatio();
                        if (i==0){
                            mapaaux= new LinkedHashMap<String,Integer>();
                            oriaux=mapaid.get(ori);
                        }
                        if (!oriaux.equals(mapaid.get(ori))){
                            mapa.put(oriaux, mapaaux);
                            i=0;
                            oriaux=mapaid.get(ori);
                            mapaaux= new LinkedHashMap<String,Integer>();
                        }
                        rat=round(rat/*+minutos_sim*/);
                        mapaaux.put(mapaid.get(des), rat);
                        i++;
                    }
                    mapa.put(oriaux, mapaaux);
                    Simu.setArbolRatios(mapa);
                }
                catch (HibernateException ex)
                {
                    transaccion.rollback();
                    System.err.println("Got an exception! ");
                    System.err.println(ex.getMessage());
                }finally {
                   sesion.close(); // cierro la sesion (BD)
                }
    }
    
     public static Integer buscarRatiosBD(Integer origen,Integer destino){
        Integer i=-1;
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        Transaction transaccion = null;
        try
                {
                    transaccion = sesion.beginTransaction();
                    List ratios = sesion.createQuery("from RatioVuelo where id_ciudad_origen= "+origen+" and id_ciudad_destino= "+destino).list();   // query para obtener todas los ratios
                    Iterator iterador = ratios.iterator(); 
                    boolean a=iterador.hasNext();
                    if (a==true){
                        i=1;
                    }
                }
                catch (HibernateException ex)
                {
                    transaccion.rollback();
                    System.err.println("Got an exception! ");
                    System.err.println(ex.getMessage());
                }finally {
                   sesion.close(); // cierro la sesion (BD)
                }
         return i; 
     }
    
     public static void agregarRatiosBD(Integer origen,Integer destino,Integer ratio){
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        Transaction transaccion = null;
        try
                {
                    transaccion = sesion.beginTransaction();
                    RatioVueloId idtemp = new RatioVueloId();
                    idtemp.setIdCiudadOrigen(origen);
                    idtemp.setIdCiudadDestino(destino);
                    RatioVuelo ratiovue= new RatioVuelo();
                    ratiovue.setId(idtemp);
                    ratiovue.setRatio(ratio);
                    sesion.save(ratiovue);   // query para obtener todas los ratios
                    transaccion.commit();
                }
                catch (HibernateException ex)
                {
                    transaccion.rollback();
                    System.err.println("Got an exception! ");
                    System.err.println(ex.getMessage());
                }finally {
                   sesion.close(); // cierro la sesion (BD)
                }
     }
     
     public static void actualizarRatiosBD(Integer origen,Integer destino,Integer ratio){
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        Transaction transaccion = null;
        try
                {
                    transaccion = sesion.beginTransaction();
                    RatioVueloId idtemp = new RatioVueloId();
                    idtemp.setIdCiudadOrigen(origen);
                    idtemp.setIdCiudadDestino(destino);
                    RatioVuelo ratiovue= (RatioVuelo)sesion.get(RatioVuelo.class, idtemp);   // query para obtener todas los ratios
                    ratiovue.setRatio(ratio);
                    transaccion.commit();

                }
                catch (HibernateException ex)
                {
                    transaccion.rollback();
                    System.err.println("Got an exception! ");
                    System.err.println(ex.getMessage());
                }finally {
                   sesion.close(); // cierro la sesion (BD)
                }
     }
}


    